'sound manager
#include once "fmod.bi"
#include once "ext/detail/common.bi"

namespace resource.sound.fmod

type effect as _effect
type music as _music

type Manager
public:
    declare constructor()
    declare destructor()

    declare function addEffect( byref filename as string, byref shortname as string ) as ext.bool
    declare function addMusic( byref filename as string, byref shortname as string ) as ext.bool

    declare sub play( byref sname as const string )
    declare sub stop( byref sname as const string )
    declare function isPlaying( byref sname as const string ) as ext.bool

    declare property Volume( byref sname as const string, byval v as ubyte )
    declare property Volume( byref sname as const string ) as ubyte

    declare sub defaultVolume( byval v as ubyte )

    declare property masterMusicVolume( ) as ubyte
    declare property masterMusicVolume( byval v as ubyte )
    declare property masterEffectVolume( ) as ubyte
    declare property masterEffectVolume( byval v as ubyte )

    declare property looping( byref sname as string ) as ext.bool
    declare property looping( byref sname as string, byval s as ext.bool )

    declare function loadEffectsNow( ) as integer

    declare function getEffectHandle( byref sname as string ) as FSOUND_SAMPLE ptr
    declare function getMusicHandle( byref sname as string ) as FSOUND_Stream ptr

private:
    m_master_mus_vol as ubyte
    m_master_efx_vol as ubyte
    m_def_volume as ubyte
    m_efx_len as uinteger
    m_efx as Effect ptr
    m_mus_len as uinteger
    m_mus as Music ptr
end type

end namespace
'end interface

'begin implementation

namespace resource.sound.fmod

type _effect
    as string _fname
    as string _sname
    as FSOUND_Sample ptr _res
    as integer _chan
    declare destructor()
    declare constructor( byref filename as string, byref s as string )
    declare function load() as ext.bool
    declare sub play()
end type

constructor _effect( byref filename as string, byref s as string )
    _fname = filename
    _sname = s
end constructor

function _effect.load() as ext.bool

    if _res = 0 then _res = FSOUND_Sample_Load(FSOUND_FREE,_fname,FSOUND_HW2D or FSOUND_LOOP_OFF, 0, 0)
    if _res <> 0 then return true
    return false

end function

sub _effect.play()

    if _res = 0 then
        if load() = ext.false then return
    end if

    _chan = FSOUND_PlaySoundEx( FSOUND_FREE, _res,0,0 )
    FSOUND_Update()
end sub

destructor _effect()
    FSOUND_Sample_Free( _res )
end destructor

type _music
    as string _fname
    as string _sname
    as FSOUND_Stream ptr _res
    declare static function _chan( byval c as integer = FSOUND_FREE ) as integer
    declare destructor()
    declare constructor( byref filename as string, byref s as string )
    declare function load() as ext.bool
    declare sub play()
end type

constructor _music( byref filename as string, byref s as string )
    _fname = filename
    _sname = s
end constructor

function _music.load() as ext.bool

    if _res = 0 then _res = FSOUND_Stream_Open( sngfile, FSOUND_LOOP_OFF, 0, 0 )
    if _res <> 0 then return true
    return false

end function

static function _music._chan( byval c as integer = FSOUND_FREE ) as integer

    static _c as integer
    if c = FSOUND_FREE then return _c
    _c = c
    return _c

end function

sub _music.play()

    if _res = 0 then
        if load() = ext.false then return
    end if

    var chan = FSOUND_Stream_Play(_chan, _res)
    if chan <> _chan then _chan(chan)

end sub

destructor _music()
    FSOUND_Stream_Close( _res )
end destructor

destructor Manager()

    if m_efx <> 0 then delete[] m_efx
    if m_mus <> 0 then delete[] m_mus

    FSOUND_Close()

end destructor

end namespace
